package org.jeecg.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信服务端API工具类
 *
 * @author chechen
 * @date 2021-01-24
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WxUtil {

    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
    private static final String CODE_UNLIMITED = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";

    private final RedisUtil redisUtil;

    /**
     * 小程序唯一凭证，即 AppID
     */
    @Value("${pay.wx.miniAppId}")
    private String appId;
    /**
     * 小程序唯一凭证密钥，即 AppSecret
     */
    @Value("${pay.wx.miniAppSecret}")
    private String secret;

    /**
     * 获取小程序全局唯一后台接口调用凭据（access_token）
     *
     * @return AccessToken
     * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html">微信官方文档 auth.getAccessToken</a>
     */
    public String getAccessToken() {
        /* 先判断redis中有没有，没有就去请求 */
        Object accessTokenRedisObject = redisUtil.get(CacheConstant.WECHAT_APPLET_ACCESS_TOKEN);
        if (accessTokenRedisObject != null) {
            return accessTokenRedisObject.toString();
        }
        JSONObject resultJsonObject = JSON.parseObject(HttpClientUtil.doGet(String.format("%s?grant_type=client_credential&appid=%s&secret=%s",
                ACCESS_TOKEN_URL, appId, secret)));

       log.info(resultJsonObject.toJSONString());

        /* 判断是否请求成功，根据错误码并返回相应错误信息 */
        if (resultJsonObject.containsKey("errcode")) {
            Integer errCode = resultJsonObject.getInteger("errcode");
            String errorMessage;
            if (errCode == -1) {
                errorMessage = "系统繁忙，此时请稍候再试";
            } else if (errCode == 40001) {
                errorMessage = "AppSecret 错误或者 AppSecret 不属于这个小程序，请开发者确认 AppSecret 的正确性";
            } else if (errCode == 40002) {
                errorMessage = "请确保 grant_type 字段值为 client_credential";
            } else if (errCode == 40013) {
                errorMessage = "不合法的 AppID，请开发者检查 AppID 的正确性，避免异常字符，注意大小写";
            } else {
                errorMessage = resultJsonObject.getString("errmsg");
            }
            throw new JeecgBootException(errorMessage);
        }

        /* 请求成功，存入 redis 并返回 */
        // access_token 获取到的凭证
        String accessToken = resultJsonObject.getString("access_token");
        log.info(accessToken);
        // expires_in 凭证有效时间，单位：秒（目前是7200秒之内的值）
        redisUtil.set(CacheConstant.WECHAT_APPLET_ACCESS_TOKEN, accessToken, resultJsonObject.getInteger("expires_in"));
        return accessToken;
    }

    /**
     * 获取小程序码
     * 适用于需要的码数量极多的业务场景
     * 通过该接口生成的小程序码，永久有效，数量暂无限制
     *
     * @param shopId  店铺id
     * @param goodsId 商品id
     * @return 图片 Buffer
     * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html">微信官方文档 wxacode.getUnlimited</a>
     */
    public byte[] getCodeUnlimited(String shopId, String goodsId) {
        Map<String, String> params;
        /* 判断 goodsId 是否为空，为空则只返回店铺小程序码，不为空返回商品小程序码 */
        if (StringUtils.isBlank(goodsId) || CommonUtils.isNumber(goodsId)) {
            params = new HashMap<>(2);
            params.put("scene", shopId);
            params.put("page", "pages/shopinfo/index");
        } else {
            params = new HashMap<>(2);
            params.put("scene", goodsId);
            params.put("page", "pages/goodsinfo/index");
        }
        return HttpClientUtil.doPostJSONBuffer(String.format("%s?access_token=%s",
                CODE_UNLIMITED, this.getAccessToken()), JSON.toJSONString(params));
    }
}
